From: Carlos Garnacho Date: Wed, 7 Dec 2022 19:50:53 +0000 (+0100) Subject: tray: Add NaXembed object X-Git-Tag: archive/raspbian/50.5-1+rpi1~1^2~393^2^2~40 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=f9519f4a55d95e51b7397206d9d7c6cf570fa125;p=gnome-shell.git tray: Add NaXembed object This GObject subclass is a minimal wrapper similar to GtkSocket, meant to replace the GTK widgetry involved in the tray manager. Part-of: --- diff --git a/src/tray/meson.build b/src/tray/meson.build index 139e3b297..092e7f689 100644 --- a/src/tray/meson.build +++ b/src/tray/meson.build @@ -2,11 +2,13 @@ tray_sources = [ 'na-tray-child.c', 'na-tray-child.h', 'na-tray-manager.c', - 'na-tray-manager.h' + 'na-tray-manager.h', + 'na-xembed.c', + 'na-xembed.h' ] libtray = static_library('tray', tray_sources, c_args: ['-DG_LOG_DOMAIN="notification_area"'], - dependencies: [clutter_dep, gtk_dep], + dependencies: [mutter_dep, gtk_dep], include_directories: conf_inc ) diff --git a/src/tray/na-xembed.c b/src/tray/na-xembed.c new file mode 100644 index 000000000..5dbb37234 --- /dev/null +++ b/src/tray/na-xembed.c @@ -0,0 +1,882 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* Copyright (C) 2022 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * Author: Carlos Garnacho + * + * Based on GTK+ code by Owen Taylor + */ + +#include "config.h" + +#include "na-xembed.h" + +#include +#include +#include +#include + +typedef struct _NaXembedPrivate NaXembedPrivate; + +struct _NaXembedPrivate +{ + MetaX11Display *x11_display; + Window socket_window; + Window plug_window; + + int root_x; + int root_y; + int request_width; + int request_height; + int current_width; + int current_height; + int resize_count; + int xembed_version; + + unsigned int event_func_id; + guint resize_id; + + XVisualInfo *xvisual_info; + + Atom atom__XEMBED; + Atom atom__XEMBED_INFO; + Atom atom_WM_NORMAL_HINTS; + + gboolean have_size; + gboolean need_map; + gboolean is_mapped; + gboolean has_alpha; +}; + +/* XEMBED messages */ +typedef enum _XembedMessageType XembedMessageType; + +enum _XembedMessageType { + XEMBED_EMBEDDED_NOTIFY, + XEMBED_WINDOW_ACTIVATE, + XEMBED_WINDOW_DEACTIVATE, + XEMBED_REQUEST_FOCUS, + XEMBED_FOCUS_IN, + XEMBED_FOCUS_OUT, + XEMBED_FOCUS_NEXT, + XEMBED_FOCUS_PREV, + XEMBED_GRAB_KEY, + XEMBED_UNGRAB_KEY, + XEMBED_MODALITY_ON, + XEMBED_MODALITY_OFF, +}; + +/* Flags for _XEMBED_INFO */ +#define XEMBED_MAPPED (1 << 0) + +#define XEMBED_PROTOCOL_VERSION 1 + +G_DEFINE_TYPE_WITH_PRIVATE (NaXembed, na_xembed, G_TYPE_OBJECT) + +enum { + PLUG_ADDED, + PLUG_REMOVED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0, }; + +enum { + PROP_0, + PROP_X11_DISPLAY, + N_PROPS +}; + +static GParamSpec *props[N_PROPS] = { 0, }; + +static void +xembed_send_message (NaXembed *xembed, + Window recipient, + XembedMessageType message, + glong detail, + glong data1, + glong data2) +{ + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + XClientMessageEvent xclient; + + memset (&xclient, 0, sizeof (xclient)); + xclient.window = recipient; + xclient.type = ClientMessage; + xclient.message_type = priv->atom__XEMBED; + xclient.format = 32; + xclient.data.l[0] = 0; /* Time */ + xclient.data.l[1] = message; + xclient.data.l[2] = detail; + xclient.data.l[3] = data1; + xclient.data.l[4] = data2; + + meta_x11_error_trap_push (priv->x11_display); + XSendEvent (meta_x11_display_get_xdisplay (priv->x11_display), + recipient, + False, NoEventMask, (XEvent*) &xclient); + meta_x11_error_trap_pop (priv->x11_display); +} + +static void +na_xembed_end_embedding (NaXembed *xembed) +{ + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + + priv->plug_window = None; + priv->current_width = 0; + priv->current_height = 0; + priv->resize_count = 0; + g_clear_handle_id (&priv->resize_id, g_source_remove); +} + +static void +na_xembed_send_configure_event (NaXembed *xembed) +{ + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + XConfigureEvent xconfigure; + + memset (&xconfigure, 0, sizeof (xconfigure)); + xconfigure.type = ConfigureNotify; + + xconfigure.event = priv->plug_window; + xconfigure.window = priv->plug_window; + + xconfigure.x = priv->root_x; + xconfigure.y = priv->root_y; + xconfigure.width = priv->current_width; + xconfigure.height = priv->current_height; + + xconfigure.border_width = 0; + xconfigure.above = None; + xconfigure.override_redirect = False; + + meta_x11_error_trap_push (priv->x11_display); + XSendEvent (meta_x11_display_get_xdisplay (priv->x11_display), + priv->plug_window, + False, NoEventMask, + (XEvent*) &xconfigure); + meta_x11_error_trap_pop (priv->x11_display); +} + +static void +na_xembed_synchronize_size (NaXembed *xembed) +{ + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + Display *xdisplay = meta_x11_display_get_xdisplay (priv->x11_display); + int x, y, width, height; + + x = priv->root_x; + y = priv->root_y; + width = priv->request_width; + height = priv->request_height; + + XMoveResizeWindow (xdisplay, + priv->socket_window, + x, y, + width, height); + + if (priv->plug_window) + { + meta_x11_error_trap_push (priv->x11_display); + + if (width != priv->current_width || + height != priv->current_height) + { + XMoveResizeWindow (xdisplay, + priv->plug_window, + 0, 0, + width, height); + if (priv->resize_count) + priv->resize_count--; + + priv->current_width = width; + priv->current_height = height; + } + + if (priv->need_map) + { + XMapWindow (xdisplay, priv->plug_window); + priv->need_map = FALSE; + } + + while (priv->resize_count) + { + na_xembed_send_configure_event (xembed); + priv->resize_count--; + } + + meta_x11_error_trap_pop (priv->x11_display); + } +} + +static gboolean +synchronize_size_cb (gpointer user_data) +{ + NaXembed *xembed = user_data; + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + + na_xembed_synchronize_size (xembed); + priv->resize_id = 0; + + return G_SOURCE_REMOVE; +} + +static void +na_xembed_resize (NaXembed *xembed) +{ + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + XSizeHints hints; + long supplied; + + g_clear_handle_id (&priv->resize_id, g_source_remove); + + meta_x11_error_trap_push (priv->x11_display); + + priv->request_width = 1; + priv->request_height = 1; + + if (XGetWMNormalHints (meta_x11_display_get_xdisplay (priv->x11_display), + priv->plug_window, + &hints, &supplied)) + { + if (hints.flags & PMinSize) + { + priv->request_width = MAX (hints.min_width, 1); + priv->request_height = MAX (hints.min_height, 1); + } + else if (hints.flags & PBaseSize) + { + priv->request_width = MAX (hints.base_width, 1); + priv->request_height = MAX (hints.base_height, 1); + } + } + + priv->have_size = TRUE; + meta_x11_error_trap_pop (priv->x11_display); + + priv->resize_id = g_idle_add (synchronize_size_cb, xembed); +} + +static gboolean +na_xembed_get_info (NaXembed *xembed, + Window xwindow, + unsigned long *version, + unsigned long *flags) +{ + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + MetaX11Display *x11_display = priv->x11_display; + Display *xdisplay = meta_x11_display_get_xdisplay (x11_display); + Atom type; + int format; + unsigned long nitems, bytes_after; + unsigned char *data; + unsigned long *data_long; + int status; + + meta_x11_error_trap_push (x11_display); + status = XGetWindowProperty (xdisplay, + xwindow, + priv->atom__XEMBED_INFO, + 0, 2, False, + priv->atom__XEMBED_INFO, + &type, &format, + &nitems, &bytes_after, &data); + meta_x11_error_trap_pop (x11_display); + + if (status != Success) + return FALSE; + if (type == None) + return FALSE; + + if (type != priv->atom__XEMBED_INFO) + { + g_warning ("_XEMBED_INFO property has wrong type"); + XFree (data); + return FALSE; + } + + if (nitems < 2) + { + g_warning ("_XEMBED_INFO too short"); + XFree (data); + return FALSE; + } + + data_long = (unsigned long *)data; + if (version) + *version = data_long[0]; + if (flags) + *flags = data_long[1] & XEMBED_MAPPED; + + XFree (data); + return TRUE; +} + +static void +na_xembed_add_window (NaXembed *xembed, + Window xid, + gboolean need_reparent) +{ + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + Display *xdisplay = meta_x11_display_get_xdisplay (priv->x11_display); + XVisualInfo template = { 0, }; + int n_xvisuals; + unsigned long version; + unsigned long flags; + + priv->plug_window = xid; + + meta_x11_error_trap_push (priv->x11_display); + + XSelectInput (xdisplay, + priv->plug_window, + StructureNotifyMask | PropertyChangeMask); + + if (meta_x11_error_trap_pop_with_return (priv->x11_display)) + { + priv->plug_window = None; + return; + } + + /* OK, we now will reliably get destroy notification on socket->plug_window */ + + meta_x11_error_trap_push (priv->x11_display); + + if (need_reparent) + { + XSetWindowAttributes socket_attrs; + XWindowAttributes plug_attrs; + int result; + + result = XGetWindowAttributes (xdisplay, priv->plug_window, &plug_attrs); + if (result == 0) + { + meta_x11_error_trap_pop (priv->x11_display); + priv->plug_window = None; + return; + } + + template.visualid = plug_attrs.visual->visualid; + priv->xvisual_info = + XGetVisualInfo (meta_x11_display_get_xdisplay (priv->x11_display), + VisualIDMask, + &template, + &n_xvisuals); + + if (!priv->xvisual_info) + { + meta_x11_error_trap_pop (priv->x11_display); + priv->plug_window = None; + return; + } + + priv->has_alpha = (priv->xvisual_info->depth > + __builtin_popcount (priv->xvisual_info->red_mask | + priv->xvisual_info->green_mask | + priv->xvisual_info->blue_mask)); + + socket_attrs.override_redirect = True; + + priv->socket_window = + XCreateWindow (xdisplay, + meta_x11_display_get_xroot (priv->x11_display), + -100, -100, 1, 1, 0, + priv->xvisual_info->depth, + InputOutput, + plug_attrs.visual, + CWOverrideRedirect, + &socket_attrs); + + XUnmapWindow (xdisplay, priv->plug_window); /* Shouldn't actually be necessary for XEMBED, but just in case */ + XReparentWindow (xdisplay, + priv->plug_window, + priv->socket_window, + 0, 0); + } + + priv->have_size = FALSE; + + priv->xembed_version = -1; + if (na_xembed_get_info (xembed, priv->plug_window, &version, &flags)) + { + priv->xembed_version = MIN (XEMBED_PROTOCOL_VERSION, version); + priv->is_mapped = (flags & XEMBED_MAPPED) != 0; + } + else + { + /* FIXME, we should probably actually check the state before we started */ + priv->is_mapped = TRUE; + } + + priv->need_map = priv->is_mapped; + + meta_x11_error_trap_pop (priv->x11_display); + + meta_x11_error_trap_push (priv->x11_display); + XFixesChangeSaveSet (xdisplay, priv->plug_window, + SetModeInsert, SaveSetRoot, SaveSetUnmap); + meta_x11_error_trap_pop (priv->x11_display); + + xembed_send_message (xembed, + priv->plug_window, + XEMBED_EMBEDDED_NOTIFY, 0, + priv->socket_window, + priv->xembed_version); + + na_xembed_resize (xembed); + + g_signal_emit (xembed, signals[PLUG_ADDED], 0); + + XMapWindow (xdisplay, priv->socket_window); +} + +static void +na_xembed_handle_map_request (NaXembed *xembed) +{ + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + + if (!priv->is_mapped) + { + priv->is_mapped = TRUE; + priv->need_map = TRUE; + na_xembed_resize (xembed); + } +} + +static void +na_xembed_handle_unmap_notify (NaXembed *xembed) +{ + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + + if (priv->is_mapped) + { + priv->is_mapped = FALSE; + na_xembed_resize (xembed); + } +} + +static void +xembed_filter_func (MetaX11Display *x11_display, + XEvent *xevent, + gpointer user_data) +{ + NaXembed *xembed = user_data; + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + Display *xdisplay = meta_x11_display_get_xdisplay (priv->x11_display); + + if (priv->socket_window == None) + return; + if (xevent->xany.window != priv->socket_window && + xevent->xany.window != priv->plug_window) + return; + + switch (xevent->type) + { + case ClientMessage: + /* We choose to ignore all _XEMBED ClientEvent messages + * addressed to the socket. + */ + break; + case CreateNotify: + { + XCreateWindowEvent *xcwe = &xevent->xcreatewindow; + + if (!priv->plug_window) + na_xembed_add_window (xembed, xcwe->window, FALSE); + + break; + } + case ConfigureRequest: + { + XConfigureRequestEvent *xcre = &xevent->xconfigurerequest; + + if (!priv->plug_window) + na_xembed_add_window (xembed, xcre->window, FALSE); + + if (priv->plug_window) + { + if (xcre->value_mask & (CWWidth | CWHeight)) + { + priv->resize_count++; + na_xembed_resize (xembed); + } + else if (xcre->value_mask & (CWX | CWY)) + { + na_xembed_send_configure_event (xembed); + } + + /* Ignore stacking requests. */ + } + break; + } + case DestroyNotify: + { + XDestroyWindowEvent *xdwe = &xevent->xdestroywindow; + + /* Note that we get destroy notifies both from SubstructureNotify on + * our window and StructureNotify on socket->plug_window + */ + if (priv->plug_window && (xdwe->window == priv->plug_window)) + { + g_object_ref (xembed); + g_signal_emit (xembed, signals[PLUG_REMOVED], 0); + na_xembed_end_embedding (xembed); + g_object_unref (xembed); + } + break; + } + case MapRequest: + if (!priv->plug_window) + na_xembed_add_window (xembed, xevent->xmaprequest.window, FALSE); + + if (priv->plug_window == xevent->xmaprequest.window) + na_xembed_handle_map_request (xembed); + break; + case PropertyNotify: + if (priv->plug_window && + xevent->xproperty.window == priv->plug_window) + { + if (xevent->xproperty.atom == priv->atom_WM_NORMAL_HINTS) + { + priv->have_size = FALSE; + na_xembed_resize (xembed); + } + else if (xevent->xproperty.atom == priv->atom__XEMBED_INFO) + { + unsigned long flags; + + if (na_xembed_get_info (xembed, priv->plug_window, NULL, &flags)) + { + gboolean was_mapped = priv->is_mapped; + gboolean is_mapped = (flags & XEMBED_MAPPED) != 0; + + if (was_mapped != is_mapped) + { + if (is_mapped) + { + na_xembed_handle_map_request (xembed); + } + else + { + meta_x11_error_trap_push (priv->x11_display); + XMapWindow (xdisplay, priv->plug_window); + meta_x11_error_trap_pop (priv->x11_display); + + na_xembed_handle_unmap_notify (xembed); + } + } + } + } + } + break; + case ReparentNotify: + { + XReparentEvent *xre = &xevent->xreparent; + + if (priv->plug_window == None && + xre->parent == priv->socket_window) + { + na_xembed_add_window (xembed, xre->window, FALSE); + } + else if (priv->plug_window != None && + xre->window == priv->plug_window && + xre->parent != priv->socket_window) + { + g_object_ref (xembed); + g_signal_emit (xembed, signals[PLUG_REMOVED], 0); + na_xembed_end_embedding (xembed); + g_object_unref (xembed); + } + + break; + } + case UnmapNotify: + if (priv->plug_window != None && + xevent->xunmap.window == priv->plug_window) + na_xembed_handle_unmap_notify (xembed); + break; + } +} + +static void +na_xembed_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + NaXembed *xembed = NA_XEMBED (object); + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + + switch (prop_id) + { + case PROP_X11_DISPLAY: + priv->x11_display = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +na_xembed_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NaXembed *xembed = NA_XEMBED (object); + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + + switch (prop_id) + { + case PROP_X11_DISPLAY: + g_value_set_object (value, priv->x11_display); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +na_xembed_finalize (GObject *object) +{ + NaXembed *xembed = NA_XEMBED (object); + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + + g_clear_pointer (&priv->xvisual_info, XFree); + + if (priv->x11_display && priv->event_func_id) + meta_x11_display_remove_event_func (priv->x11_display, priv->event_func_id); + + if (priv->plug_window) + na_xembed_end_embedding (xembed); + + G_OBJECT_CLASS (na_xembed_parent_class)->finalize (object); +} + +static void +na_xembed_constructed (GObject *object) +{ + NaXembed *xembed = NA_XEMBED (object); + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + Display *xdisplay; + + G_OBJECT_CLASS (na_xembed_parent_class)->constructed (object); + + xdisplay = meta_x11_display_get_xdisplay (priv->x11_display); + + priv->event_func_id = + meta_x11_display_add_event_func (priv->x11_display, + xembed_filter_func, + object, + NULL); + + priv->atom__XEMBED = XInternAtom (xdisplay, "_XEMBED", False); + priv->atom__XEMBED_INFO = XInternAtom (xdisplay, "_XEMBED_INFO", False); + priv->atom_WM_NORMAL_HINTS = XInternAtom (xdisplay, "WM_NORMAL_HINTS", False); +} + +static void +na_xembed_class_init (NaXembedClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = na_xembed_set_property; + object_class->get_property = na_xembed_get_property; + object_class->finalize = na_xembed_finalize; + object_class->constructed = na_xembed_constructed; + + signals[PLUG_ADDED] = + g_signal_new ("plug-added", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NaXembedClass, plug_added), + NULL, NULL, NULL, + G_TYPE_NONE, 0); + + signals[PLUG_REMOVED] = + g_signal_new ("plug-removed", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NaXembedClass, plug_removed), + NULL, NULL, NULL, + G_TYPE_NONE, 0); + + props[PROP_X11_DISPLAY] = + g_param_spec_object ("x11-display", + "x11-display", + "x11-display", + META_TYPE_X11_DISPLAY, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY); + + g_object_class_install_properties (object_class, N_PROPS, props); +} + +static void +na_xembed_init (NaXembed *xembed) +{ +} + +void +na_xembed_add_id (NaXembed *xembed, + Window window) +{ + na_xembed_add_window (xembed, window, TRUE); +} + +Window +na_xembed_get_plug_window (NaXembed *xembed) +{ + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + + return priv->plug_window; +} + +Window +na_xembed_get_socket_window (NaXembed *xembed) +{ + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + + return priv->socket_window; +} + +void +na_xembed_set_root_position (NaXembed *xembed, + int x, + int y) +{ + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + + if (priv->root_x == x && + priv->root_y == y) + return; + + priv->root_x = x; + priv->root_y = y; + + if (priv->resize_id == 0) + priv->resize_id = g_idle_add (synchronize_size_cb, xembed); +} + +MetaX11Display * +na_xembed_get_x11_display (NaXembed *xembed) +{ + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + + return priv->x11_display; +} + +void +na_xembed_get_size (NaXembed *xembed, + int *width, + int *height) +{ + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + + if (width) + *width = priv->request_width; + if (height) + *height = priv->request_height; +} + +static void +get_pixel_details (unsigned long pixel_mask, + int *shift, + int *precision) +{ + unsigned long m = 0; + int s = 0; + int p = 0; + + if (pixel_mask != 0) + { + m = pixel_mask; + while (!(m & 0x1)) + { + s++; + m >>= 1; + } + + while (m & 0x1) + { + p++; + m >>= 1; + } + } + + if (shift) + *shift = s; + if (precision) + *precision = p; +} + +void +na_xembed_set_background_color (NaXembed *xembed, + const ClutterColor *color) +{ + NaXembedPrivate *priv = na_xembed_get_instance_private (xembed); + XVisualInfo *xvisual_info; + Display *xdisplay; + unsigned long pixel; + + if (!priv->socket_window) + return; + if (!priv->xvisual_info) + return; + + xvisual_info = priv->xvisual_info; + + if (priv->has_alpha) + { + pixel = 0; + } + else + { + double red, green, blue; + int red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec; + unsigned int padding; + + /* Shifting by >= width-of-type isn't defined in C */ + if (xvisual_info->depth >= 32) + padding = 0; + else + padding = ((~(uint32_t)0)) << xvisual_info->depth; + + red = (double) color->red / 255.0; + green = (double) color->green / 255.0; + blue = (double) color->blue / 255.0; + + get_pixel_details (xvisual_info->red_mask, &red_shift, &red_prec); + get_pixel_details (xvisual_info->green_mask, &green_shift, &green_prec); + get_pixel_details (xvisual_info->blue_mask, &blue_shift, &blue_prec); + + pixel = ~(xvisual_info->red_mask | + xvisual_info->green_mask | + xvisual_info->blue_mask | + padding); + + pixel += (((int) (red * ((1 << red_prec) - 1))) << red_shift) + + (((int) (green * ((1 << green_prec) - 1))) << green_shift) + + (((int) (blue * ((1 << blue_prec) - 1))) << blue_shift); + } + + xdisplay = meta_x11_display_get_xdisplay (priv->x11_display); + + XSetWindowBackground (xdisplay, priv->socket_window, pixel); + XClearWindow (xdisplay, priv->socket_window); +} diff --git a/src/tray/na-xembed.h b/src/tray/na-xembed.h new file mode 100644 index 000000000..ec46119d4 --- /dev/null +++ b/src/tray/na-xembed.h @@ -0,0 +1,63 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* na-xembed.h + * Copyright (C) 2022 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * Author: Carlos Garnacho + */ + +#ifndef NA_XEMBED_H +#define NA_XEMBED_H + +#include +#include +#include + +G_BEGIN_DECLS + +#define NA_TYPE_XEMBED (na_xembed_get_type ()) +G_DECLARE_DERIVABLE_TYPE (NaXembed, na_xembed, NA, XEMBED, GObject) + +struct _NaXembedClass +{ + GObjectClass parent_class; + + void (* plug_added) (NaXembed *xembed); + void (* plug_removed) (NaXembed *xembed); +}; + +MetaX11Display * na_xembed_get_x11_display (NaXembed *xembed); + +void na_xembed_add_id (NaXembed *xembed, + Window window); + +Window na_xembed_get_plug_window (NaXembed *xembed); + +Window na_xembed_get_socket_window (NaXembed *xembed); + +void na_xembed_set_root_position (NaXembed *xembed, + int x, + int y); + +void na_xembed_get_size (NaXembed *xembed, + int *width, + int *height); + +void na_xembed_set_background_color (NaXembed *xembed, + const ClutterColor *color); + +G_END_DECLS + +#endif /* NA_XEMBED_H */